<?php
/*
SELECT 
    COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,COLUMN_TYPE,COLUMN_COMMENT
FROM 
    information_schema.columns
WHERE 
    1=1
    AND table_name = 'page' 
    AND table_schema = 'zero'
*/
class Page extends CoreModule {
	public static $arOut=array(), //protected 
		$parse_uri=array(),
		$pageOut = array('header'=>null, 'main'=>null, 'footer'=>null  ),
		$path404 = '/404.php',
		$login = '/login',
		$forbidden = '/forbidden',
		$out_modules_max_recours = 100,
		$page_property = array (
		  'page_path' => '',
		  'parent_path' => '',/* not from DB */
		  
		  'page_alias' => '',
		  'page_access' => NULL,

		  'page_template' => '',
		  'parent_template' => '',/* not from DB */
		  'main_template' => '',/* not from DB */
		  
		  'page_title' => '',
		  'page_meta_desc' => '',
		  'page_meta_key' => '',
		  'page_add_head' => '',
		  'page_html' => '',
		  'page_load_from_db' => NULL,
		  'page_note' => '',
		);
		
	public static $fromDB = '', 
	$messages = array( 'success'=>array(), 'warning'=>array(), 'error'=>array(), );
	
	
	/**
	*	message
	*
	*	запись сообщений в массив или получений
	*	( в зависимости от переданного параметра $_value )
	*	@param string $type - тип сообщения, ключ в массиве self::$messages
	*	@param string $name - имя сообщения, для привязки к полю формы например; если $name=null генерится ключ = длинне массива
	*	@param string $_value - само сообщение
	*/	
	static function message( $type, $name=null, $_value=null ){
		if(!isset( self::$messages[ $type ] )) self::$messages[ $type ] = array();
		if(is_null($name)) $name = count( self::$messages[ $type ] );
		return self::_get_set( self::$messages[ $type ], $name, $_value );	
	}
	
	/**
	*	outMessages
	*
	*	вывод сообщений на страницу, используя заполненный массив self::$messages
	*	@param	string $template_file  - абсолютный путь к шаблону
	*/	
	static function outMessages( $template_file=null ) {
		if(is_null($template_file)) $template_file = _DOCUMENT_ROOT.TMPL_DEFAULT.'/'.'page_messages.php';
		if( is_file($template_file) )
			return self::includeInOb( $template_file, self::$messages );
		else 
			throw new Exception( __METHOD__.': '.Lang::get( '{FILE}_DOESNT_EXISTS', array('{FILE}'=>$template_file) ) );
	}
	
	protected static function start( array $options=null) {}
	
	/**
	*	buildPageOut
	*
	*	Сборка вывода страницы
	*	@param string $URI - адрес запроса
	*/	
	protected static function buildPageOut( $URI='' ) {
		if(empty( $URI )) $URI=$_SERVER['REQUEST_URI'];
		//$parse_url = self::parse_url( $URI ); 
		self::$parse_uri = $parse_uri = parse_uri( $URI ); //myPrint($parse_uri,'$parse_uri' );
		
		if( !empty( $URI ) && $URI!='/favicon.ico' ) {
			$_SESSION['lastURI']= $URI;
		}
		
		$path = $parse_uri['path'];
		if( $path!='/') $path = rtrim( $path, '/');/* убираем последний слеш  */
		
			
		$template = TMPL_DEFAULT;
		/* get page from db 
			self::$fromDB = $fromDB = self::getPageFromDB( $path ); //myPrint($fromDB, '$getPageFromDB');
			if( isset($fromDB['is_in_dbase']) && !empty($fromDB['page_load_from_db'])) self::$pageOut['main'] = $fromDB['page_html'];
			
			self::$arOut['meta_keywords']=$fromDB['page_meta_key'];
			self::$arOut['meta_description']=$fromDB['page_meta_desc'];
			self::$arOut['add_head']=$fromDB['page_add_head'];
			self::$arOut['title']= $fromDB['page_title'];
			// выбор шаблона
				 if( !empty( $fromDB['page_template'] ) )	$template = $fromDB['page_template'];
			else if( !empty( $fromDB['parent_template'] ) )	$template = $fromDB['parent_template'];
			else if( !empty( $fromDB['main_template'] ) )	$template = $fromDB['main_template'];
				if( empty($template) ) $template = TMPL_DEFAULT;
			
			//self::$pageOut['template']=_IS_AJAX ? $template :'<script type="text/javascript">var _TEMPLATE_="'.$template.'"</script>';
		// get page from db 
		*/ 
		
		self::getPageProperties( $parse_uri['module'], $parse_uri['path']); //myPrint(self::$arOut, '$arOut');
		// check access 	
		$accessArr = self::$arOut['access'];
		if(is_array($accessArr) && count($accessArr)>0){
			$arIntersect = array_intersect($_SESSION['user']['access'], $accessArr);	
			if(count($arIntersect)<1 ){
				if( empty($_SESSION['user']['sign']) ){ 
					$_SESSION['redirect']=$URI;
					$_SERVER['REQUEST_URI'] = self::$login;
					self::buildPageOut(); return;
				} else {
					$_SERVER['REQUEST_URI'] = self::$forbidden;
					self::buildPageOut(); return;
				}
			}
		}
		
		if(isset(self::$arOut['template'])) $template=self::$arOut['template'];
		/* get page from file */
		if( $template!='NONE' ){
			self::$pageOut['header'] = self::getContentFromUri( $template.DIRECTORY_SEPARATOR.(_IS_AJAX ? 'header_ajax.php' : 'header.php') );
			self::$pageOut['footer'] = self::getContentFromUri( $template.DIRECTORY_SEPARATOR.(_IS_AJAX ? 'footer_ajax.php' : 'footer.php') );		
		}
		if(is_null(self::$pageOut['main'])){
			//if($parse_uri['module']=='admin') self::$pageOut['main'] = self::getContentFromUri( $path ); else
			if($parse_uri['module']=='ajax' && _IS_AJAX/**/) self::$pageOut['main'] = self::getContentFromUri( $path ); else
			self::$pageOut['main'] = self::getContentFromUri( '/'.$parse_uri['module'] );//$path		
		} 

		/**/
		if(is_null(self::$pageOut['main'])){
			self::$pageOut['main'] = self::return404();
		}
	}
	
	static function return404(){
		header( "HTTP/1.1 404 Not Found" );
		$path404 = _DOCUMENT_ROOT.self::$path404;
		if( is_file($path404) ) {
			self::$arOut['getContentFrom'] = $path404;
			return self::includeInOb( $path404 );
		}
	}
	
	/**
	*	getContentFromUri
	*
	*	получение контента страницы из файла
	*	@param string $path - путь к файлу
	*	@return string - контент страницы или null
	*/
	static function getContentFromUri( $path ){ 
		$prefixes = array( '','index','/index'  );
		$exts = array( '','.php','.html','.html'  );
		
		foreach( $prefixes as $prefix)
			foreach( $exts as $ext){
				$filepath = _DOCUMENT_ROOT.$path.$prefix.$ext;
				if( is_file($filepath) ) { 
					self::$arOut['getContentFrom'] = $filepath;
					$out = self::includeInOb( $filepath, self::$arOut );	
					return $out;
				}
			}
		return null;	
	}
	
	/**
	*	outSubPage
	*
	*	вывод подстраницы из URI 
	*	Общий принцип: из пути /clients/vtb24bank/project1 выпарсиваются 
	*	"clients" как module и "vtb24bank/project1" как params
	*	первоначально всегда загружается /module в качестве страницы (см. buildPageOut), 
	* 	а params могут использоваться как параметры, или как путь до подстраницы(как в этом случае)
	* 		if( Page::outSubPage() ) return;
	*
	*	@return bool - сделан какой либо вывод или нет, т.е. предполагается ли подстраница в URI, в случае отсутсвия файла подстраницы выводится 404
	*/
	static function outSubPage(){ 
		$parse_uri = self::$parse_uri;
		if($parse_uri['params']!=''){
			$cont = self::getContentFromUri( $parse_uri['path'] );
			if (is_null($cont) && $parse_uri['module']!='admin' ) $cont = self::return404();
			echo $cont;
			return true;
		}
		return false;
	}
	
	
	/**
	*	getPageProperties
	*
	*	взятие свойств страницы из глобального массива $pageProperties,
	*	проверка на наличие в исключающием глобальном массиве $withoutTemplate (строить без шаблона),	
	*	@param string $module - модуль страницы, ключ в массиве свойств $pageProperties	
	*	@path string $module - путь страницы, ключ в массиве свойств $pageProperties	
	*	@return boolean - найдены ли свойства.
	*/
	static function getPageProperties( $module, $path ){ 
		global $pageProperties, $withoutTemplate;
		if( is_array( $pageProperties ) ){
			//foreach( $pageProperties[''] as $name=>$prop ) self::$arOut[$name] = $prop;// default
			self::$arOut = $pageProperties[''];
			if( array_key_exists( $module, $pageProperties ))
				foreach( $pageProperties[$module] as $name=>$prop ) self::$arOut[$name] = $prop;
			if( is_array( $withoutTemplate ) && in_array( $path, $withoutTemplate ) ){
				self::$arOut['template'] = 'NONE';
			}
			return true;
		}
		return false;
	}	
	
	/**
	*	getPageProp
	*
	*	взятие свойств страницы из массива $pageProps из файла $filePath 
	*	@param string $filePath - путь до файла с массивом $pageProps
	*	@param string $pagePath - путь страницы, ключ в массиве свойств $pageProps	
	*	@return boolean - найдены ли свойства.
	*/
	static function getPagePropsFromFile($filePath, $pagePath){ 
		$filepath = _DOCUMENT_ROOT.$filePath;
		if( is_file($filepath) ) { 
			include_once( $filepath );	
			if(is_array($pageProps) && array_key_exists( $pagePath, $pageProps ))
				foreach( $pageProps[$pagePath] as $name=>$prop ) self::$arOut[$name] = $prop;
			return true;
		}
		return false;
	}	
	/**
	*	Массив родительских путей
	*
	*	как "/admin" и "/admin/modules" для "/admin/modules/page.php"
	*	@param string $path - путь
	*	@return array
	*/
	static function getParentPath( $path  ){
		$parent=''; $res=array(); 
		$path = rtrim( $path, '/'); /* убираем последний слеш  */
		$arPath = explode('/', $path );
		array_shift( $arPath  ); array_pop( $arPath  );
		foreach( $arPath as $p){
			$parent.='/'.$p; 
			$res[] = $parent;
		}
		return $res;
	}
	
	/**
	*	Массив свойств родителя
	*
	*	как "/admin" и "/admin/modules" для "/admin/modules/page.php"
	*	@param string $path - путь
	*	@return array
	*/
	static function getParentProp( $path  ){
		$page_table = DB::$tables['page'];
		/* имена полей таблицы */
		$page_path = 'page_path';
		$page_alias = 'page_alias';
		
		$parent_page_prop = array();
		$parent_path=self::getParentPath($path);
		if( count($parent_path)>0 ){
			$page_prop['$parent_path'] = $parent_path;
			$where_or=''; /* условие WHERE ... OR ... */
			 /* создаем строку ... OR ... для всех найденных разделов */
			foreach( $parent_path as $p_path )
				$where_or.=' OR '.'`'.$page_path.'`="'.$p_path.'" OR `'.$page_alias.'`="'.$p_path.'"';
			/* обрезаем первый OR */
			$where_or = ltrim( $where_or, ' OR' );
			/* берем свойства родителя, включая ДОСТУП */
			$sql='SELECT `page_template` AS `parent_template`, `page_path` AS `parent_path`, '.
				'`page_access`, `page_title`,`page_meta_desc`,`page_meta_key`,`page_add_head`  '.
				'FROM `'.$page_table.'` WHERE '.$where_or.' ORDER BY  `'.$page_path.'` desc';
			$parent_page_prop= exec_sql2array( $sql );			
		}
		return $parent_page_prop;
	}
	
	/**
	*	getPageFromDB
	*
	*	получение свойств страницы из базы данных
	*	@param string $path - путь в строке адреса как идентификатор
	*	@return array - массив  свойств страницы 
	*/
	static function getPageFromDB( $path  ){
		$page_table= DB::$tables['page'];
		/* имена полей таблицы */
		$page_path = 'page_path';
		$page_alias = 'page_alias';
		
		$page_prop = self::$page_property;
		/* декодируем символы */
		$path = urldecode( $path );
		$page_prop['$path'] = $path;
		
		/* подмешиваем свойства главной страницы : page_template */
		$_page_prop = exec_sql2array('SELECT `page_template` AS `main_template` FROM `'.$page_table.'` WHERE `'.$page_path.'`="/" ;');
		$page_prop = array_merge( $page_prop, $_page_prop[0] );
		//$page_prop['main_template'] = $page_prop['page_template'];
		
		/* ищем страницу по пути или псевдониму */
		$curr_page_prop= exec_sql2array('SELECT * FROM `'.$page_table.
			'` WHERE `'.$page_path.'`="'.$path.'" OR `'.$page_alias.'`="'.$path.'" ;');

		if( count($curr_page_prop)>0 ) 
		$page_prop = array_merge($page_prop, end($curr_page_prop) );
		
		/* вычисляем свойства родительских разделОВ как "/admin" и "/admin/modules" для "/admin/modules/page.php" */
		$prnt_page_prop = self::getParentProp( $path );
		
		if( count($prnt_page_prop)>0 ){//isset($prnt_page_prop) && 
			$page_prop = array_merge($page_prop, $prnt_page_prop[0]); $page_prop['$parent_path_prop']=$prnt_page_prop[0];
		}
		
		/* массив доступа десериализуем  */
		$page_prop['page_access'] = unserialize( $page_prop['page_access'] );
		
		/* успешно нашли в базе, либо это главная и настройки должны быть хоть какие то */
		if( $path=='/' || count($curr_page_prop)>0) $page_prop['is_in_dbase'] = true;
		
		return $page_prop;
	}
	
	/**
	* 	insertModuleOut
	*
	*	Возврат результата работы модуля, от вывова {ИМЯ_КЛАССА}::Out()
	*	на результаты работы этих модулей, возвращаемые Page::insertModuleOut,
	*	Page::insertModuleOut рекурсивно вызывает outModules для поиска новых строк типа "<!--Module::Auth()-->" внутри модулей...
	*
	*	@param array $moduleNameArr - где [1] - имя класса, [2] - параметры в формате json
	*	@param string 
	*/
/*	
	static function insertModuleOut( $moduleNameArr ){ 
		if( !class_exists($moduleNameArr[1]) ) {
			$ermess = Lang::get('ERROR_MODULE_INCLUDING').
				Lang::get( '{MODULE}_DOESNT_EXISTS', array('{MODULE}'=>$moduleNameArr[1]) );
			$res = Debug::localError( $ermess );
		}else {
			$params = json_decode( $moduleNameArr[2], true);	//echo $moduleNameArr[1].'::Out<br/>'; myPrint($params, '$params');
			$res=call_user_func( $moduleNameArr[1].'::Out', $params ); 

			$res = self::outModules( $res, $moduleNameArr[1].'::Out( '.( count($params)>0 ? implode( ', ', $params ) : '' ).' )');
		}
		//echo 'res='.$res;
		return $res; 
	}
*/	
	/**
	* 	outModules
	*
	*	Вывод модулей путем замены строк типа "<!--Module::Auth()-->"
	*	на результаты работы этих модулей, возвращаемые Page::insertModuleOut,
	*	Page::insertModuleOut рекурсивно вызывает outModules для поиска модулей внутри модулей...
	*	$moduleNameOut - имя очередного модуля, не передается при первом вызове, для сброса счетчика рекурсий
	*	максимальное количество рекурсий, и предотвращение зацикливания регулируется переменной self::$out_modules_max_recours
	*
	*	@param string $content - контент для замены 
	*	@param string $moduleNameOut - имя очередного модуля
	
	static function outModules( $content, $moduleNameOut=false ){
		
		static $recours; //echo $content.'<br/>';
		if( !$moduleNameOut ) $recours=0; else $recours++;
		
		if( $recours>self::$out_modules_max_recours ){
			$ermess = 'Рекурсия подключения модулей свыше '.self::$out_modules_max_recours.' на '.$moduleNameOut;
			$res = Debug::localError( $ermess );
			exit($res);
		}
		return preg_replace_callback( '/<!--\s*Module::([^(]*)\(([^)]*)\)\s*-->/U', 'Page::insertModuleOut' , $content );
	}
*/	
	/**
	*	Out
	*
	*	Вывод результатов работы модуля - страницы
	*/
	static function Out( array $options=null ) {
		self::buildPageOut(); 
		
		return self::$pageOut;
		
		if(!_IS_AJAX){
			//ob_start();
				//foreach( self::$pageOut as $content ) if( !is_null($content) ) echo $content;
			//return ob_get_clean();
			
			//$parse_url = self::parse_url( $_SERVER['REQUEST_URI'] );
			/* исключаем страницу редактирования самих страниц 
			if( $parse_url['path']=='/admin/modules/content/PageProperty.php')
				return $fullcontent;
			else
				return self::outModules( $fullcontent );
			*/
		}else{
			//foreach( self::$pageOut as $key=>$content ) self::$pageOut[$key] = self::outModules( $content );
			//return self::$pageOut['main']; //только то что вернул ajax
		}
		
	}
	
}
?>